#include <time.h>
#include <omp.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include "init.h"
#include "ScnsInclude.h"
#include "JctoInclude.h"

static pthread_t pthreadIds[3]; //0 lcdFlush;1 smctpSend;2 smctpReceive

static uint8 pthreadRunFlag[3];

static volatile uint8 lcdSyncFlag;

#if defined(__linux__)
static void Sleep(uint32 ms)
{
    usleep(10*1000);
}
#endif

void stop(int sign)
{
#if defined(SCNS_SMCTP_ENABLE)&&SCNS_SMCTP_ENABLE==1
    if(scnsSmctpCanSend(SCNS_SMCTP_CHANNEL_DEBUG,0)==SCNS_STATUS_NOT_INITED)
    {
        return;
    }
    vmWaitLcdSync();
    pthreadRunFlag[0]=0;
    pthread_join(pthreadIds[0],NULL);
    pthreadRunFlag[2]=0;
    pthread_join(pthreadIds[2],NULL);
    pthreadRunFlag[1]=0;
    pthread_join(pthreadIds[1],NULL);
    extern JctoSocketHandle socketFd;
    jctoSocketClose(&socketFd);
#endif
}

static void*lcdSync(void*p)
{
#if defined(SCNS_SMCTP_ENABLE)&&SCNS_SMCTP_ENABLE==1
    if(scnsSmctpCanSend(SCNS_SMCTP_CHANNEL_DEBUG,0)==SCNS_STATUS_NOT_INITED)
    {
        return NULL;
    }
    while(pthreadRunFlag[0])
    {
        ScnsImage*image=scnsLcdScreenShot(SCNS_COLOR_FORMAT_RGB888,1);
        scnsSmctpExtImageSend(SCNS_SMCTP_CHANNEL_IMAGE,image);
        scnsSmctpExtImageWaitCanSend(SCNS_SMCTP_CHANNEL_IMAGE,image,1);
        scnsImageFree(image);
        ++lcdSyncFlag;
        Sleep(10);
    }
#endif
    return NULL;
}

void vmWaitLcdSync()
{
#if defined(SCNS_SMCTP_ENABLE)&&SCNS_SMCTP_ENABLE==1
    if(scnsSmctpCanSend(SCNS_SMCTP_CHANNEL_DEBUG,0)==SCNS_STATUS_NOT_INITED||(!pthreadRunFlag[0])){return;}
    lcdSyncFlag=0;
    while(lcdSyncFlag<=1){Sleep(1);}
#endif
}

static void*smctpSend(void*p)
{
#if defined(SCNS_SMCTP_ENABLE)&&SCNS_SMCTP_ENABLE==1
    if(scnsSmctpCanSend(SCNS_SMCTP_CHANNEL_DEBUG,0)==SCNS_STATUS_NOT_INITED)
    {
        return NULL;
    }
    while(pthreadRunFlag[1])
    {
        while(SCNS_STATUS_OK!=scnsSmctpFlushBuf()){}
        Sleep(4);
    }
    while(SCNS_STATUS_OK!=scnsSmctpFlushBuf()){}
#endif
    return NULL;
}

static void*smctpReceive(void*p)
{
#if defined(SCNS_SMCTP_ENABLE)&&SCNS_SMCTP_ENABLE==1
    if(scnsSmctpCanSend(SCNS_SMCTP_CHANNEL_DEBUG,0)==SCNS_STATUS_NOT_INITED)
    {
        return NULL;
    }
    while(pthreadRunFlag[2])
    {
        uint8 data[4096];
        extern JctoSocketHandle socketFd;
        int len=jctoSocketRecv(&socketFd,data,4096);
        if(len<=0){break;}
        scnsSmctpReceive(data,len);
        Sleep(4);
    }
#endif
    return NULL;
}

void init(void)
{
    srand(time(0));
    omp_set_nested(10);
    signal(SIGINT,stop);
    signal(SIGTERM,stop);
    pthreadRunFlag[1]=1;
    pthreadRunFlag[2]=1;
    //pthreadRunFlag[0]=1;

    uint16 errN=0;
    uint64 displayUs=0;
    static const Point errPlu={0,0};

    jctoSocketStart();
    scnsTryInit(SCNS_STATUS_OK,scnsYingInit());
#if defined(SCNS_SMCTP_ENABLE)&&SCNS_SMCTP_ENABLE==1
    scnsTryInit(SCNS_STATUS_OK,scnsSmctpInit());
#endif
    pthread_create(&pthreadIds[1],NULL,smctpSend,NULL);
    pthread_create(&pthreadIds[2],NULL,smctpReceive,NULL);
    scnsTryInit(SCNS_STATUS_OK,scnsMenuInit());
    scnsTryInit(SCNS_STATUS_OK,scnsTimerInit());
    scnsTryInit(SCNS_STATUS_OK,scnsLcdInit());
    pthread_create(&pthreadIds[0],NULL,lcdSync,NULL);
    scnsTryInit(SCNS_STATUS_OK,scnsKeyInit());

    scnsMenuSetMode(SCNS_MENU_MODE_SMCTP|SCNS_MENU_MODE_KEY|SCNS_MENU_MODE_LCD);
    scnsMenuSetNowPage(2);
    scnsMenuFresh();

    hxPrintfFL("Init finish\n");
    scnsMenuLoadAll();
}
